package com.vict.task.config;

import com.alibaba.fastjson.parser.ParserConfig;
import com.vict.task.utils.LocalTaskIdUtils;
import com.vict.task.utils.PatternUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.yaml.snakeyaml.Yaml;

import javax.annotation.PostConstruct;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;

@Slf4j
@Order(1)
@MapperScan("com.vict.task.dao")
@Component(LocalTaskCommon.beanName_taskCommon)
public class LocalTaskCommon {
    /**
     * StringRedisTemplateBean名称
     */
    public static final String beanName_redisConfig = "taskStringRedisTemplate";
    public static final String beanName_taskCommon = "localTaskCommon";

    public static Environment environment;

    public static boolean proEnvironment; // pro环境

    public static Long taskScanTime = 30L * 1000L; // 任务执行器扫描频率
    public static Long taskScanTime_extend = ((Double)(taskScanTime.doubleValue() * 2.5)).longValue(); // 任务执行器扫描时间向后偏移量  0-------------<=now + taskScanTime_extend------------oo


    public static String lockImpl = "jdk";
    public static final String lockImpl_redis = "redis";
    public static final String lockImpl_jdk = "jdk";
    public static String lockPrx; // 锁前缀
    public static String springApplicationName; // 服务名称 serverName
    public static String serverId; // 服务id 每个服务一个id

    public static boolean taskSelfFlag; // task只执行自己标记

    public static String redis_host;
    public static int redis_port;
    public static String redis_password;
    public static int redis_database;
    public static int redis_timeout;
    public static int redis_pool_max_active;
    public static int redis_pool_max_wait;
    public static int redis_pool_max_idle;
    public static int redis_pool_minIidle;
    public static String hostName;

    // 服务器标识
    public static boolean publicServerFlag = true;

    @Autowired
    public void setEnvironment(Environment environment){
        LocalTaskCommon.environment = environment;
    }

    private static Map framworkConfigMap;

    public static String getFramworkPropertyWithNotPri(String key){
        String envPri = "";
        if(!LocalTaskCommon.proEnvironment){
            envPri = "dev.";
        } else{
            envPri = "pro.";
        }
        return getFramworkProperty(envPri + key);
    }
    public static String getFramworkProperty(String key){

        String[] keyArr = key.split("\\.");

        Map tempMap = framworkConfigMap;

        for(int i = 0 ; i < keyArr.length ; i++){
            if(i == keyArr.length - 1){
                // 最后一个
                Object o = tempMap.get(keyArr[i]);

                if(o instanceof String){
                    return (String)o;
                }else if(o instanceof Integer){
                    return ((Integer)o).toString();
                }else if(o instanceof Double){
                    return ((Double)o).toString();
                }else if(o instanceof Float){
                    return ((Float)o).toString();
                }else if(o instanceof Long){
                    return ((Long)o).toString();
                }
            }else{
                tempMap = (Map)tempMap.get(keyArr[i]);
            }
        }

        return null;
    }

    public static <T> T  getFramworkProperty(String key, Class<T> clazz){

        String[] keyArr = key.split("\\.");

        Map tempMap = framworkConfigMap;

        for(int i = 0 ; i < keyArr.length ; i++){
            if(i == keyArr.length - 1){
                // 最后一个
                T o = (T)tempMap.get(keyArr[i]);
                return o;
            }else{
                tempMap = (Map)tempMap.get(keyArr[i]);
            }
        }

        return null;
    }

    static{
        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
        // // 程序初始化
        // 程序环境初始化
        String systemEnv = System.getenv("SPRING_PROFILES_ACTIVE");
        if(systemEnv != null){
            if(systemEnv.trim().equals("pro")){
                LocalTaskCommon.proEnvironment = true;
            }else{
                LocalTaskCommon.proEnvironment = false;
            }
        }
        String springbootEnv = System.getenv("spring.profiles.active");
        if(springbootEnv != null){
            if(springbootEnv.trim().equals("pro")){
                LocalTaskCommon.proEnvironment = true;
            }else{
                LocalTaskCommon.proEnvironment = false;
            }
        }

        String systemCmd = System.getProperty("sun.java.command");
        try{
            String systemCmd2 = PatternUtil.matcherOne("--spring.profiles.active=[a-zA-Z]{3}", systemCmd);
            if(systemCmd2 != null && systemCmd2.length() >= 3){
                String systemCmdEnv = systemCmd2.substring(systemCmd2.length() - 3, systemCmd2.length());
                if(systemCmdEnv != null && systemCmdEnv.equals("pro")){
                    LocalTaskCommon.proEnvironment = true;
                }else{
                    LocalTaskCommon.proEnvironment = false;
                }
            }
        }catch(Exception e){
            System.out.println();
        }
        try{
            String systemCmd3 = PatternUtil.matcherOne("--serverFlag=[a-zA-Z]{10}", systemCmd);
            if(systemCmd3 != null && systemCmd3.length() >= 10){
                String serverFlagStr = systemCmd3.substring(systemCmd3.length() - 10, systemCmd3.length());
                if(serverFlagStr != null && serverFlagStr.equals("serverFlag")){
                    LocalTaskCommon.publicServerFlag = true;
                }else{
                    LocalTaskCommon.publicServerFlag = false;
                }
            }else{
                LocalTaskCommon.publicServerFlag = false;
            }
        }catch(Exception e){
            System.out.println();
        }

        // // 框架初始化
        // 读取框架yaml
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream inputStream = classLoader.getResourceAsStream("application-task.yml");
        Yaml yaml = new Yaml();
        LocalTaskCommon.framworkConfigMap = (Map)yaml.load(inputStream);

        // 配置前缀
        String envPri = "";
        if(!LocalTaskCommon.proEnvironment){
            envPri = "dev.";
        } else{
            envPri = "pro.";
        }
        log.info("启动环境 {}", envPri);

        // lock实现
        // lock实现方式
        LocalTaskCommon.lockImpl = getFramworkProperty(envPri + "lockImpl");
        if(LocalTaskCommon.lockImpl == null){
            throw new RuntimeException("没有配置lockImpl, [redis, jdk]");
        }

        // hostName初始化
        InetAddress localhost = null;
        try {
            localhost = InetAddress.getLocalHost();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        LocalTaskCommon.hostName = localhost.getHostName();

        // 服务id 初始化
        LocalTaskCommon.serverId = LocalTaskIdUtils.getSalt(64, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".toCharArray());
    }

    @SneakyThrows
    @PostConstruct
    public void init(){
        // 配置前缀
        String envPri = "";
        if(!LocalTaskCommon.proEnvironment){
            envPri = "dev.";
        } else{
            envPri = "pro.";
        }

        // redis
        LocalTaskCommon.redis_host = getFramworkProperty(envPri + "redis.redis_host");
        LocalTaskCommon.redis_port = getFramworkProperty(envPri + "redis.redis_port", Integer.TYPE);
        LocalTaskCommon.redis_password = getFramworkProperty(envPri + "redis.redis_password");
        LocalTaskCommon.redis_database = getFramworkProperty(envPri + "redis.redis_database", Integer.TYPE);
        LocalTaskCommon.redis_timeout = getFramworkProperty(envPri + "redis.redis_timeout", Integer.TYPE);
        LocalTaskCommon.redis_pool_max_active = getFramworkProperty(envPri + "redis.redis_pool_max_active", Integer.TYPE);
        LocalTaskCommon.redis_pool_max_wait = getFramworkProperty(envPri + "redis.redis_pool_max_wait", Integer.TYPE);
        LocalTaskCommon.redis_pool_max_idle = getFramworkProperty(envPri + "redis.redis_pool_max_idle", Integer.TYPE);
        LocalTaskCommon.redis_pool_minIidle =  getFramworkProperty(envPri + "redis.redis_pool_minIidle", Integer.TYPE);
        log.info("redis配置初始化完毕");

        // // 程序初始化
        // 是否自身task
        if(LocalTaskCommon.publicServerFlag == false) { // 不是服务器
            String taskSelfFlag = Optional.ofNullable(LocalTaskCommon.environment.getProperty("localTaskSelfFlag")).map(o -> o.trim()).filter(o -> !o.equals("")).orElse(null);
            if(taskSelfFlag != null){
                LocalTaskCommon.taskSelfFlag = true;
            }else{
                LocalTaskCommon.taskSelfFlag = false;
            }
        }else{
            // 是服务器
            LocalTaskCommon.taskSelfFlag = false;
        }

        // 服务名称
        LocalTaskCommon.springApplicationName = LocalTaskCommon.environment.getProperty("spring.application.name");
        if(LocalTaskCommon.springApplicationName == null){
            throw new RuntimeException("没有配置spring.application.name");
        }

        // lock前缀 初始化
        LocalTaskCommon.lockPrx = LocalTaskCommon.environment.getProperty("spring.application.name");

        log.info("framworkCommon初始化完成");
        log.info("serverId:{}", LocalTaskCommon.serverId);
    }
}
